use axum_common::extractor::{TypedHeader, ValidJson};
use axum_common::header::{System, SystemType};
use axum_common::middleware::Principal;
use axum_common::rediss::RedisJson;
use axum_common::{configuration, rediss, util, ApiResult, R};
use redis::AsyncCommands;
use serde::{Deserialize, Serialize};
use validator::Validate;

#[tracing::instrument(name = "login", skip_all, fields(account = %params.account))]
pub async fn login(TypedHeader(System(system_type)): TypedHeader<System>, ValidJson(params): ValidJson<LoginParams>) -> R<LoginResponse> {
    tracing::info!("开始处理登录逻辑...");

    if params.account != "admin" || params.password != "123456" {
        return R::fail("用户名或密码错误");
    }

    let principal = Principal {
        id: 1,
        name: "admin".to_string(),
    };
    save_user(principal, system_type).await.into()
}


/// 将用户信息保存在redis中
pub async fn save_user(principal: Principal, system_type: SystemType) -> ApiResult<LoginResponse> {
    let token = util::uuid_simple();
    let mut connect = rediss::get().await?;
    let json = RedisJson(principal.clone());
    let expire = match system_type {
        SystemType::Sys => configuration::auth().sys_expire(),
        _ => configuration::auth().app_expire(),
    };
    let _: () = connect
        .set_ex(
            &token,
            json,
            expire,
        )
        .await?;

    Ok(LoginResponse {
        id: principal.id,
        name: principal.name,
        token,
    })
}

#[derive(Debug, Deserialize, Validate)]
pub struct LoginParams {
    #[validate(length(min = 3, max = 16, message = "账号长度为3-16"))]
    account: String,
    #[validate(length(min = 6, max = 16, message = "密码长度为6-16"))]
    password: String,
}

#[derive(Debug, Serialize, Validate)]
#[serde(rename_all(serialize = "snake_case"))]
pub struct LoginResponse {
    id: i64,
    name: String,
    token: String,
}
